package org.hiro.actions;

import static com.intellij.ide.util.EditSourceUtil.getDescriptor;
import com.intellij.openapi.actionSystem.DataContext;
import static com.intellij.openapi.application.ApplicationManager.getApplication;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import static com.intellij.openapi.ui.Messages.showMessageDialog;
import com.intellij.openapi.util.Computable;
import com.intellij.pom.Navigatable;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiModifier;
import org.hiro.psi.GeneratedBuilderClassBuilder;
import org.hiro.psi.PsiHelper;

class GenerateBuilderActionHandler extends EditorActionHandler {

    public void execute(Editor editor, DataContext dataContext) {
        final PsiHelper psiHelper = new PsiHelper(dataContext);
        final PsiClass classToBuild = psiHelper.getCurrentClass();
        final Project project = psiHelper.getProject();

        if (classToBuild!= null && classToBuild.getModifierList().getText().contains(PsiModifier.ABSTRACT)) {
            showMessageDialog(project, "Cannot generate a builder for an abstract class", "Warning", Messages.getWarningIcon());
            return;
        }

        PsiClass builderClass = getApplication().runWriteAction(
            new Computable<PsiClass>() {
                public PsiClass compute() {
                    return new GeneratedBuilderClassBuilder(psiHelper.getElementFactory(), project, psiHelper.getCodeStyleManager())
                            .withClassToBuild(classToBuild)
                            .build();
                }
            });

        if (builderClass != null) {
            jumpToBuilderClass(builderClass);
        }
    }

    private void jumpToBuilderClass(PsiClass psiClass) {
        Navigatable navigatable = getDescriptor(psiClass);
        if (navigatable != null) {
            navigatable.navigate(true);
        }
    }
}
